﻿using MongoDB.Driver;
using Sustainalytics.Claims;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ProductInvolvement;
using Sustainalytics.Entities.SustainableProducts;
using Sustainalytics.MongoDB.Extensions;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Web.Http;

namespace Sustainalytics.ScreeningTool.Service.Utility
{
    public static class ScreeningToolClaimsCheckerExtensions
    {
        public const string PIRoutePrefix = "api/v1/pi";
        public const string SPRoutePrefix = "api/v1/sp";

        public static bool ValidateCriteria(this IClaimsChecker claimsChecker, ApiController controller, string shortName, string symbol)
        {
            bool valid = false;

            if (!string.IsNullOrWhiteSpace(symbol))
                return claimsChecker.Validate(controller, new List<Entities.ResourceParameters>() { new ResourceParameters { Key = GetKey(symbol), Value = symbol.ToLowerInvariant() } });

            if (shortName != null)
                valid = claimsChecker.Validate(controller, new List<Entities.ResourceParameters>() { new ResourceParameters { Key = "shortName", Value = shortName.ToLowerInvariant() } });

            return valid;
        }

        public static string GetKey(string symbol)
        {
            string result = "";

            bool isPi = MongoFactory.GetCollectionFromDatabase<ProductInvolvementFramework>(MongoFactory.GetConnectionStrings().ProductInvolvementDW)
                        .Find(Builders<ProductInvolvementFramework>.Filter.Eq(p => p.Symbol, symbol)).Count() > 0;

            if (isPi) result = "pi";
            else
            {
                bool isSp = MongoFactory.GetCollectionFromDatabase<SustainableProductsFramework>(MongoFactory.GetConnectionStrings().ProductInvolvementDW)
                        .Find(Builders<SustainableProductsFramework>.Filter.Eq(p => p.Symbol, symbol)).Count() > 0;
                if (isSp) result = "sp";
            }
            return result;
        }

        public static bool ValidateRoute(this IClaimsChecker claimsChecker, ApiController controller)
        {
            if (claimsChecker.Validate(controller, new List<Entities.ResourceParameters>() { }))
                return true;
            return false;
        }

        public static bool ValidateAnyShortName(this IClaimsChecker claimsChecker, ApiController controller)
        {
            List<string> shortNames = new List<string>() { "fullaccess", "compinfo", "business", "financial", "esg", "ratings", "environment", "social", "governance", "events" };

            foreach (var sn in shortNames)
            {
                if (claimsChecker.Validate(controller, new List<Entities.ResourceParameters>() { new ResourceParameters { Key = "shortName", Value = sn.ToLowerInvariant() } }))
                    return true;
            }

            return false;
        }

        public static bool Validate(this IClaimsChecker claimsChecker, ApiController ctrl, List<ResourceParameters> parameters)
        {
            // get current principal
            var principal = (ClaimsPrincipal)ctrl.User;

            // get route prefix
            object[] attrs = ctrl.GetType().GetCustomAttributes(typeof(RoutePrefixAttribute), false);
            RoutePrefixAttribute routePrefixAttrs = attrs.Length == 0 ? null : attrs.Select(a => (RoutePrefixAttribute)a).FirstOrDefault();

            // get HTTP Method
            string httpMethod = ctrl.Request.Method.Method;
            string routePrefix = routePrefixAttrs == null ? null : routePrefixAttrs.Prefix;

            if (parameters.Any(c => c.Key.ToLowerInvariant() == "pi"))
                routePrefix = PIRoutePrefix;

            if (parameters.Any(c => c.Key.ToLowerInvariant() == "sp"))
                routePrefix = SPRoutePrefix;

            bool valid = claimsChecker.Validate(
                claimsPrincipal: principal,
                resource: routePrefix,
                verb: httpMethod,
                parameters: parameters);

            return valid;
        }
    }
}
